package picoevo.app.chemicalreactions;

import picoevo.core.Population;

public class Global_CR {

	// ## General ##
	
	static final String[] enzymes = {"E1","E2","E3"};
	static final String[] products = {"X", "Y", "Z"};
	static final String waste = "waste";
	
	static final double P_init_enzymaticReaction = 0.5; // in ]0,1[ (ie. extreme values may slow down particular initialization or mutation operations, which may require a specific reaction type) 

	// ### ### INITIALIZATION ### ### 
	
	// ## Individual ##
	
	static final int nbReactionsMin_atInit = 3;
	static final int nbReactionsMax_atInit = 5;
	static final int nbReactionsMin = 3;
	static final int nbReactionsMax = 10; //7? //25?
	
	// Comment 2014-01-08: from 0.1 to 10, either continuous of steps (10^-1 or 10^0 or 10^1) 
	static final double KmMinPowValue = -1; // -1    
	static final double KmMaxPowValue = 1; // 5
	static final double KiMinPowValue = -1; // 0
	static final double KiMaxPowValue = 1; // 5
	
	static final double KplusMinPowValue = -1; // -4
	static final double KplusMaxPowValue = 1; // 5
	static final double KminusMinPowValue = -1; // -4
	static final double KminusMaxPowValue = 1; // 5
	
	// ## Reactions ##

	// enzymatic
	static final double P_init_rightProductOne_enzymaticReaction_waste = 0.2;
	static final double P_init_rightProductTwo_enzymaticReaction_waste = 0.2; // if rightProductOne is not waste already
	
	// non-enzymatic
	static final double P_init_leftProductOne_simpleReaction_waste = 0.2;
	static final double P_init_leftProductTwo_simpleReaction_waste = 0.2; // if leftProductOne is not waste already
	static final double P_init_rightProductOne_simpleReaction_waste = 0.2;
	static final double P_init_rightProductTwo_simpleReaction_waste = 0.2; // if rightProductOne is not waste already

	static final double P_init_mutate_silence_Kplus = 0.3;
	static final double P_init_mutate_silence_Kminus = 0.3; // if Kplus is not zero


	// ### ### Evolutionary Mutations ### ###

	// # Balancing between mutation families 
	// Remark: only one type of mutation is performed per variation call.
	// Below: types are grouped in block. Each type should sum to 1.0. If not, this will be normalized afterwards anyway.
	
	static final double P_onestep_indivParam = 0.45;
	static final double P_onestep_indivStructure = 0.05; 
	static final double P_onestep_reactionParam = 0.45;
	static final double P_onestep_reactionStructure = 0.05;
	
	// # reactions
	
	static final double P_mutate_product_add = 1.0/6.0;
	static final double P_mutate_product_remove = 1.0/6.0;
	static final double P_mutate_product_swap = 1.0/6.0;
	static final double P_mutate_enzyme_add = 1.0/6.0;
	static final double P_mutate_enzyme_remove = 1.0/6.0;
	static final double P_mutate_enzyme_swap = 1.0/6.0;
	
	// # individual
	
	static final double P_mutate_reaction_add = 0.25;
	static final double P_mutate_reaction_remove = 0.25;
	static final double P_mutate_reaction_decompose = 0.25; // e.g. X=>Y becomes X=>Z et Z=>Y
	static final double P_mutate_reaction_merge = 0.25; // e.g. X=Y and Y=>Z become X=>Z
	
	// matrices (K_m and k_i)
	
	static final double P_mutate_matrix_Km = 0.5;
	static final double P_mutate_matrix_ki = 0.5;
	
	static final double P_mutate_Kplus = 0.25;
	static final double P_mutate_Kminus = 0.25;
	static final double P_mutate_silence_Kplus = 0.25;
	static final double P_mutate_silence_Kminus = 0.25;
	
	// =-=-=-=-=-=

	static String getString()
	{
		String s = "";
		
		s += "Enzymes={";
		for ( int i = 0 ; i != enzymes.length ; i++ )
			s += " "+enzymes[i];
		s += " }\n";
		s += "Products={";
		for ( int i = 0 ; i != products.length ; i++ )
			s += " "+products[i];
		s += " }\n";
		s += "waste=" + waste + "\n";
		
		s += "P_init_enzymaticReaction=" + P_init_enzymaticReaction + "\n";

		s += "nbReactionsMin_atInit=" + nbReactionsMin_atInit + "\n";
		s += "nbReactionsMax_atInit=" + nbReactionsMax_atInit + "\n";
		s += "nbReactionsMin=" + nbReactionsMin + "\n";
		s += "nbReactionsMax=" + nbReactionsMax + "\n";
		
		s += "KmMinPowValue=" + KmMinPowValue + "\n";
		s += "KmMaxPowValue=" + KmMaxPowValue + "\n";
		s += "KiMinPowValue=" + KiMinPowValue + "\n";
		s += "KiMaxPowValue=" + KiMaxPowValue + "\n";
		
		s += "KplusMinPowValue=" + KplusMinPowValue + "\n";
		s += "KplusMaxPowValue=" + KplusMaxPowValue + "\n";
		s += "KminusMinPowValue=" + KminusMinPowValue + "\n";
		s += "KminusMaxPowValue=" + KminusMaxPowValue + "\n";

		s += "P_init_rightProductOne_enzymaticReaction_waste=" + P_init_rightProductOne_enzymaticReaction_waste + "\n";
		s += "P_init_rightProductTwo_enzymaticReaction_waste=" + P_init_rightProductTwo_enzymaticReaction_waste + "\n";
		
		s += "P_init_leftProductOne_simpleReaction_waste=" + P_init_leftProductOne_simpleReaction_waste + "\n";
		s += "P_init_leftProductTwo_simpleReaction_waste=" + P_init_leftProductTwo_simpleReaction_waste + "\n";
		s += "P_init_rightProductOne_simpleReaction_waste=" + P_init_rightProductOne_simpleReaction_waste + "\n";
		s += "P_init_rightProductTwo_simpleReaction_waste=" + P_init_rightProductTwo_simpleReaction_waste + "\n";

		s += "P_init_mutate_silence_Kplus=" + P_init_mutate_silence_Kplus + "\n";
		s += "P_init_mutate_silence_Kminus=" + P_init_mutate_silence_Kminus + "\n";
		
		s += "P_onestep_indivParam=" + P_onestep_indivParam + "\n";
		s += "P_onestep_indivStructure=" + P_onestep_indivStructure + "\n"; 
		s += "P_onestep_reactionParam=" + P_onestep_reactionParam + "\n";
		s += "P_onestep_reactionStructure=" + P_onestep_reactionStructure + "\n";
		
		s += "P_mutate_product_add=" + P_mutate_product_add + "\n";
		s += "P_mutate_product_remove=" + P_mutate_product_remove + "\n";
		s += "P_mutate_product_swap=" + P_mutate_product_swap + "\n";
		s += "P_mutate_enzyme_add=" + P_mutate_enzyme_add + "\n";
		s += "P_mutate_enzyme_remove=" + P_mutate_enzyme_remove + "\n";
		s += "P_mutate_enzyme_swap=" + P_mutate_enzyme_swap + "\n";
		
		s += "P_mutate_reaction_add=" + P_mutate_reaction_add + "\n";
		s += "P_mutate_reaction_remove=" + P_mutate_reaction_remove + "\n";
		s += "P_mutate_reaction_decompose=" + P_mutate_reaction_decompose + "\n";
		s += "P_mutate_reaction_merge=" + P_mutate_reaction_merge + "\n";
		
		s += "P_mutate_matrix_Km=" + P_mutate_matrix_Km + "\n";
		s += "P_mutate_matrix_ki=" + P_mutate_matrix_ki + "\n";
		s += "P_mutate_Kplus=" + P_mutate_Kplus + "\n";
		s += "P_mutate_Kminus=" + P_mutate_Kminus + "\n";
		s += "P_mutate_silence_Kplus=" + P_mutate_silence_Kplus + "\n";
		s += "P_mutate_silence_Kminus=" + P_mutate_silence_Kminus + "\n";

		return s;
	}

	public static Individual_CR returnDefaultIndividual(Population pop) {

		Individual_CR individual = new Individual_CR(pop);
		Reaction r;
		int[] signature = new int[6];
		double k_plus, k_minus;

		individual.clearReactions();
		
		double[][] m = {{ 0.22501386436794063,0.22730864337576054,0.28108812490935436},{0.5756782487875376,0.41765744973406177,0.5369647591714541},{6.02975646351803,2.6483540657182387,0.12049584119089483}};
		
		individual.setMatrixKm(m);
		
		double i[][] = {{0.5754879945569741,0.23922612370920293,0.7723403796115397},{0.5028130158823979,0.41645145080833057,8.658377386099351},{8.70619688233929,1.8381663232541876,2.5526598782937673}};
		
		individual.setMatrixKi(i);
		
		// E1 + Z ==> E1
		signature[0] = 0;
		signature[1] = 2;
		signature[2] = -1;
		signature[3] = 0;
		signature[4] = -1;
		signature[5] = -1;
		k_plus = 1.0;
		k_minus = 0.0;
		r = new Reaction();
		r.setSignature(signature);//,k_plus,k_minus);
		individual.addReaction(r);        	

		// E2 + Y ==> E2 + X + Y
		signature[0] = 1;
		signature[1] = 1;
		signature[2] = -1;
		signature[3] = 1;
		signature[4] = 0;
		signature[5] = 1;
		r = new Reaction();
		r.setSignature(signature);//,k_plus,k_minus);
		individual.addReaction(r);        	

		// Y + Z <==> Z [ k+ = 2.7529933522129375 ; k- = 3.896571002642828 ]
		signature[0] = -1;
		signature[1] = 1;
		signature[2] = 2;
		signature[3] = -1;
		signature[4] = 2;
		signature[5] = -1;
		k_plus = 2.7529933522129375;
		k_minus = 3.896571002642828;
		r = new Reaction();
		r.setSignature(signature,k_plus,k_minus);
		individual.addReaction(r);
		
		
		// Z + Z <==> Z + X [ k+ = 2.6359471733283235 ; k- = 0.609023664380919 ]
		signature[0] = -1;
		signature[1] = 2;
		signature[2] = 2;
		signature[3] = -1;
		signature[4] = 2;
		signature[5] = 0;
		k_plus = 2.6359471733283235;
		k_minus = 0.609023664380919;
		r = new Reaction();
		r.setSignature(signature,k_plus,k_minus);
		individual.addReaction(r);
		

/*		// X <==> X + X [ k+ = 1.0 ; k- = 0.0 ]
		signature[0] = -1;
		signature[1] = 0;
		signature[2] = -1;
		signature[3] = -1;
		signature[4] = 0;
		signature[5] = 0;
		k_plus = 1.0;
		k_minus = 0.0;
		r = new Reaction();
		r.setSignature(signature,k_plus,k_minus);
		individual.addReaction(r);        	

		// X + Y <==> Y + Y [ k+ = 1.0 ; k- = 0.0 ]
		signature[0] = -1;
		signature[1] = 0;
		signature[2] = 1;
		signature[3] = -1;
		signature[4] = 1;
		signature[5] = 1;
		r = new Reaction();
		r.setSignature(signature,k_plus,k_minus);
		individual.addReaction(r);        	

		// Y <==> 0 [ k+ = 1.0 ; k- = 0.0 ]
		signature[0] = -1;
		signature[1] = 1;
		signature[2] = -1;
		signature[3] = -1;
		signature[4] = -1;
		signature[5] = -1;
		k_plus = 1.0;
		k_minus = 0.0;
		r = new Reaction();
		r.setSignature(signature,k_plus,k_minus);
		individual.addReaction(r);*/        	

		return individual;
	}
}
